package de.koller.oceanFramework.glyph;

import de.koller.oceanFramework.OceanException;
import de.koller.oceanFramework.plain.Sea3P;
import de.koller.oceanFramework.plain.fullParticle.ParticleImage;
import de.koller.oceanFramework.plain.fullParticle.PondGraphics;
import de.koller.oceanFramework.tree.Child;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;

public class GlyphScreen extends Sea3P {

	public static final int GLYPH_WIDTH = 8, GLYPH_HEIGHT = 12;
	private final BufferedImage glyphs;
	private final int width, height;
	@Child private final ParticleImage szene;

	private final Glyph clearGlyph = new Glyph( 0xffffffff, 0x00000000, -1, -1 );
	private final Glyph[][] gszene;
	private final Glyph[][] gchanged;
	
	@Child private final GlyphRenderer renderer;
	
	public GlyphScreen( int width, int height, IFontValue fv, String fontpath ) {
		this.width = width;
		this.height = height;
		this.szene = new ParticleImage( width, height );
		this.gszene = new Glyph[ width/GLYPH_WIDTH + 1][ height/GLYPH_HEIGHT + 1];
		this.gchanged = new Glyph[ width/GLYPH_WIDTH + 1][ height/GLYPH_HEIGHT + 1];
		
		this.renderer = new GlyphRenderer( fv );
		
		try {
			ClassLoader cl = this.getClass().getClassLoader();
			InputStream in = cl.getResourceAsStream( fontpath );
			glyphs = ImageIO.read( in );
		} catch ( IOException ex ) {
			throw new OceanException( ex );
		}
	}
	
	@Override
	protected void render( int elapsedTime, Graphics2D g ) {
		super.render( elapsedTime, g );
		
		for( int x = 0; x < gszene.length; x++ ) 
			for( int y = 0; y < gszene[0].length; y++ )
				if( gchanged[x][y] == null || !gchanged[x][y].equals( gszene[x][y] ) ) {
					drawGlyph( x, y, gszene[x][y] );
					gchanged[x][y] = gszene[x][y];
					gszene[x][y] = clearGlyph;
				}
		
		g.drawImage( szene.getBitmap(), 0, 0, null );
	}

	public void clearGlyph( int x, int y, int color ) {
		Glyph g = new Glyph( 0, color, -1, -1 );
		renderGlyph( x, y, g );
	}
	
	public void renderGlyph( int x, int y, Glyph g ) {
		try {
			if( gszene[x][y] != null && gszene[x][y].equals( g ) )
				return;
		
			gszene[x][y] = g;
		} catch( ArrayIndexOutOfBoundsException ex ) {
			return;
		}
	}
	
	private void drawGlyph( int sx, int sy, Glyph g ) {
		if( g == null )
			return;
		
		for( int x = 0; x < GLYPH_WIDTH; x++ )
			for( int y = 0; y < GLYPH_HEIGHT; y++ ) {
				PondGraphics gp = szene.getPgraphics();
				
				int c;
				if( g.getGlyphx() == -1 && g.getGlyphy() == -1 )
					c = g.getBackColor();
				else {
					int sc = glyphs.getRGB( x + g.getGlyphx()*GLYPH_WIDTH, y + g.getGlyphy()*GLYPH_HEIGHT );
					c = sc == 0x00000000 ? g.getBackColor() : g.getFontColor();
				}
				
				gp.setPixel( c, x + sx*GLYPH_WIDTH, y + sy*GLYPH_HEIGHT );
			}
	}

	public GlyphRenderer getRenderer() {
		return renderer;
	}

	public ParticleImage getSzene() {
		return szene;
	}

}
